

<!DOCTYPE html>
<html lang="zh-CN" data-default-color-scheme=&#34;auto&#34;>



<head>
  <meta charset="UTF-8">
  <link rel="apple-touch-icon" sizes="76x76" href="/img/favicon.ico">
  <link rel="icon" href="/img/favicon.ico">
  <meta name="viewport"
        content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, shrink-to-fit=no">
  <meta http-equiv="x-ua-compatible" content="ie=edge">
  
  <meta name="theme-color" content="#2f4154">
  <meta name="description" content="叶尘的技术升级小木屋">
  <meta name="author" content="叶尘">
  <meta name="keywords" content="">
  
  <title>2.分布式组件 - 叶尘的技术升级小木屋</title>

  <link  rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.0/dist/css/bootstrap.min.css" />


  <link  rel="stylesheet" href="https://cdn.jsdelivr.net/npm/github-markdown-css@4.0.0/github-markdown.min.css" />
  <link  rel="stylesheet" href="/lib/hint/hint.min.css" />

  
    
    
      
      <link  rel="stylesheet" href="https://cdn.jsdelivr.net/npm/highlight.js@10.7.2/styles/github-gist.min.css" />
    
  

  
    <link  rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fancyapps/fancybox@3.5.7/dist/jquery.fancybox.min.css" />
  



<!-- 主题依赖的图标库，不要自行修改 -->

<link rel="stylesheet" href="//at.alicdn.com/t/font_1749284_ba1fz6golrf.css">



<link rel="stylesheet" href="//at.alicdn.com/t/font_1736178_kmeydafke9r.css">


<link  rel="stylesheet" href="/css/main.css" />

<!-- 自定义样式保持在最底部 -->

  
<link rel="stylesheet" href="//cdn.jsdelivr.net/gh/bynotes/texiao/source/css/shubiao.css">
<link rel="stylesheet" href="//cdn.jsdelivr.net/gh/bynotes/texiao/source/css/gundongtiao.css">
<link rel="stylesheet" href="//cdn.jsdelivr.net/gh/bynotes/texiao/source/css/daziyanse.css">
<link rel="stylesheet" href="//cdn.jsdelivr.net/gh/bynotes/texiao/source/css/toubudaziji.css">
<link rel="stylesheet" href="//cdn.jsdelivr.net/npm/aplayer/dist/APlayer.min.css">



  <script id="fluid-configs">
    var Fluid = window.Fluid || {};
    var CONFIG = {"hostname":"www.yechen-blog.cn","root":"/","version":"1.8.11","typing":{"enable":true,"typeSpeed":70,"cursorChar":"_","loop":false},"anchorjs":{"enable":true,"element":"h1,h2,h3,h4,h5,h6","placement":"right","visible":"hover","icon":""},"progressbar":{"enable":true,"height_px":3,"color":"#29d","options":{"showSpinner":false,"trickleSpeed":100}},"copy_btn":true,"image_zoom":{"enable":true,"img_url_replace":["",""]},"toc":{"enable":true,"headingSelector":"h1,h2,h3,h4,h5,h6","collapseDepth":0},"lazyload":{"enable":true,"loading_img":"/img/loading.gif","onlypost":false,"offset_factor":2},"web_analytics":{"enable":false,"baidu":null,"google":null,"gtag":null,"tencent":{"sid":null,"cid":null},"woyaola":null,"cnzz":null,"leancloud":{"app_id":null,"app_key":null,"server_url":null}},"search_path":"/local-search.xml"};
  </script>
  <script  src="/js/utils.js" ></script>
  <script  src="/js/color-schema.js" ></script>
<meta name="generator" content="Hexo 5.4.0"></head>


<body>
  <header style="height: 70vh;">
    <nav id="navbar" class="navbar fixed-top  navbar-expand-lg navbar-dark scrolling-navbar">
  <div class="container">
    <a class="navbar-brand"
       href="/">&nbsp;<strong>YECHEN</strong>&nbsp;</a>

    <button id="navbar-toggler-btn" class="navbar-toggler" type="button" data-toggle="collapse"
            data-target="#navbarSupportedContent"
            aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
      <div class="animated-icon"><span></span><span></span><span></span></div>
    </button>

    <!-- Collapsible content -->
    <div class="collapse navbar-collapse" id="navbarSupportedContent">
      <ul class="navbar-nav ml-auto text-center">
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/">
                <i class="iconfont icon-home-fill"></i>
                首页
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/categories/">
                <i class="iconfont icon-qrcode"></i>
                分类
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/tags/">
                <i class="iconfont icon-tags-fill"></i>
                标签
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/about/">
                <i class="iconfont icon-user-fill"></i>
                关于
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/playlist/">
                <i class="iconfont icon-music"></i>
                音乐
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item dropdown">
              <a class="nav-link dropdown-toggle" target="_self" role="button"
                 data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
                <i class="iconfont icon-books"></i>
                链接
              </a>
              <div class="dropdown-menu" aria-labelledby="navbarDropdown">
                
                  
                  
                  
                  <a class="dropdown-item" target="_blank" rel="noopener" href="https://hexo.fluid-dev.com/">
                    
                    主题博客
                  </a>
                
                  
                  
                  
                  <a class="dropdown-item" target="_blank" rel="noopener" href="https://hexo.fluid-dev.com/docs/guide/">
                    
                    配置指南
                  </a>
                
                  
                  
                  
                  <a class="dropdown-item" target="_blank" rel="noopener" href="https://hexo.fluid-dev.com/docs/icon/">
                    
                    图标用法
                  </a>
                
                  
                  
                  
                  <a class="dropdown-item" target="_blank" rel="noopener" href="https://www.bilibili.com">
                    
                    哔哩哔哩
                  </a>
                
              </div>
            </li>
          
        
        
          <li class="nav-item" id="search-btn">
            <a class="nav-link" target="_self" data-toggle="modal" data-target="#modalSearch">&nbsp;<i
                class="iconfont icon-search"></i>&nbsp;</a>
          </li>
        
        
          <li class="nav-item" id="color-toggle-btn">
            <a class="nav-link" target="_self">&nbsp;<i
                class="iconfont icon-dark" id="color-toggle-icon"></i>&nbsp;</a>
          </li>
        
      </ul>
    </div>
  </div>
</nav>

    <div class="banner" id="banner" parallax=true
         style="background: url('/img/banner.jpg') no-repeat center center;
           background-size: cover;">
      <div class="full-bg-img">
        <div class="mask flex-center" style="background-color: rgba(0, 0, 0, 0.3)">
          <div class="page-header text-center fade-in-up">
            <span class="h2" id="subtitle" title="2.分布式组件">
              
            </span>

            
              <div class="mt-3">
  
    <span class="post-meta mr-2">
      <i class="iconfont icon-author" aria-hidden="true"></i>
      叶尘
    </span>
  
  
    <span class="post-meta">
      <i class="iconfont icon-date-fill" aria-hidden="true"></i>
      <time datetime="2021-09-25 22:19" pubdate>
        星期六, 九月 25日 2021, 10:19 晚上
      </time>
    </span>
  
</div>

<div class="mt-1">
  
    
    <span class="post-meta mr-2">
      <i class="iconfont icon-chart"></i>
      3.9k 字
    </span>
  

  
    
    <span class="post-meta mr-2">
      <i class="iconfont icon-clock-fill"></i>
      
      
      50
       分钟
    </span>
  

  
  
    
      <!-- LeanCloud 统计文章PV -->
      <span id="leancloud-page-views-container" class="post-meta" style="display: none">
        <i class="iconfont icon-eye" aria-hidden="true"></i>
        <span id="leancloud-page-views"></span> 次
      </span>
    
  
</div>

            
          </div>

          
        </div>
      </div>
    </div>
  </header>

  <main>
    
      

<div class="container-fluid nopadding-x">
  <div class="row nomargin-x">
    <div class="d-none d-lg-block col-lg-2"></div>
    <div class="col-lg-8 nopadding-x-md">
      <div class="container nopadding-x-md" id="board-ctn">
        <div class="py-5" id="board">
          <article class="post-content mx-auto">
            <!-- SEO header -->
            <h1 style="display: none">2.分布式组件</h1>
            
            <div class="markdown-body">
              <h2 id="SpringCloud-Alibaba-简介"><a href="#SpringCloud-Alibaba-简介" class="headerlink" title="SpringCloud Alibaba 简介"></a>SpringCloud Alibaba 简介</h2><p><a target="_blank" rel="noopener" href="https://github.com/alibaba/spring-cloud-alibaba/blob/master/README-zh.md">github 地址</a></p>
<blockquote>
<p>Spring Cloud Alibaba 致力于提供微服务开发的一站式解决方案。此项目包含开发分布式应用微服务的必需组件，方便开发者通过 Spring Cloud 编程模型轻松使用这些组件来开发分布式应用服务。</p>
<p>依托 Spring Cloud Alibaba，您只需要添加一些注解和少量配置，就可以将 Spring Cloud 应用接入阿里微服务解决方案，通过阿里中间件来迅速搭建分布式应用系统。</p>
</blockquote>
<h3 id="主要功能"><a href="#主要功能" class="headerlink" title="主要功能"></a>主要功能</h3><ul>
<li><strong>服务限流降级</strong>：默认支持 WebServlet、WebFlux、OpenFeign、RestTemplate、Spring Cloud Gateway、Zuul、Dubbo 和 RocketMQ 限流降级功能的接入，可以在运行时通过控制台实时修改限流降级规则，还支持查看限流降级 Metrics 监控。</li>
<li><strong>服务注册与发现</strong>：适配 Spring Cloud 服务注册与发现标准，默认集成了 Ribbon 的支持。</li>
<li><strong>分布式配置管理</strong>：支持分布式系统中的外部化配置，配置更改时自动刷新。</li>
<li><strong>消息驱动能力</strong>：基于 Spring Cloud Stream 为微服务应用构建消息驱动能力。</li>
<li><strong>分布式事务</strong>：使用 @GlobalTransactional 注解， 高效并且对业务零侵入地解决分布式事务问题。</li>
<li><strong>阿里云对象存储</strong>：阿里云提供的海量、安全、低成本、高可靠的云存储服务。支持在任何应用、任何时间、任何地点存储和访问任意类型的数据。</li>
<li><strong>分布式任务调度</strong>：提供秒级、精准、高可靠、高可用的定时（基于 Cron 表达式）任务调度服务。同时提供分布式的任务执行模型，如网格任务。网格任务支持海量子任务均匀分配到所有 Worker（schedulerx-client）上执行。</li>
<li><strong>阿里云短信服务</strong>：覆盖全球的短信服务，友好、高效、智能的互联化通讯能力，帮助企业迅速搭建客户触达通道。</li>
</ul>
<h3 id="包含组件"><a href="#包含组件" class="headerlink" title="包含组件"></a>包含组件</h3><p><a target="_blank" rel="noopener" href="https://github.com/alibaba/Sentinel">Sentinel</a>：把流量作为切入点，从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。</p>
<p><a target="_blank" rel="noopener" href="https://github.com/alibaba/Nacos">Nacos</a>：一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。</p>
<p><a target="_blank" rel="noopener" href="https://rocketmq.apache.org/">RocketMQ</a>：一款开源的分布式消息系统，基于高可用分布式集群技术，提供低延时的、高可靠的消息发布与订阅服务。</p>
<p><a target="_blank" rel="noopener" href="https://github.com/apache/dubbo">Dubbo</a>：Apache Dubbo™ 是一款高性能 Java RPC 框架。</p>
<p><a target="_blank" rel="noopener" href="https://github.com/seata/seata">Seata</a>：阿里巴巴开源产品，一个易于使用的高性能微服务分布式事务解决方案。</p>
<p><a target="_blank" rel="noopener" href="https://www.aliyun.com/product/oss">Alibaba Cloud OSS</a>: 阿里云对象存储服务（Object Storage Service，简称 OSS），是阿里云提供的海量、安全、低成本、高可靠的云存储服务。您可以在任何应用、任何时间、任何地点存储和访问任意类型的数据。</p>
<p><a target="_blank" rel="noopener" href="https://help.aliyun.com/document_detail/43136.html">Alibaba Cloud SchedulerX</a>: 阿里中间件团队开发的一款分布式任务调度产品，提供秒级、精准、高可靠、高可用的定时（基于 Cron 表达式）任务调度服务。</p>
<p><a target="_blank" rel="noopener" href="https://www.aliyun.com/product/sms">Alibaba Cloud SMS</a>: 覆盖全球的短信服务，友好、高效、智能的互联化通讯能力，帮助企业迅速搭建客户触达通道。</p>
<h3 id="在项目中引入-SpringCloud-Alibaba"><a href="#在项目中引入-SpringCloud-Alibaba" class="headerlink" title="在项目中引入 SpringCloud Alibaba"></a>在项目中引入 SpringCloud Alibaba</h3><p><img src="https://cdn.jsdelivr.net/gh/yechen-ops/image-hosting@master/20210925/image.1tdsqbxoin4w.png" srcset="/img/loading.gif" lazyload alt="版本对应"></p>
<p>我们在项目中使用 <code>SpringBoot 2.2.6 2.2.6.RELEASE</code> 的版本，因此引入 <code>SpringCloud Alibaba 2.2.x</code> 的版本</p>
<p>在 common 模块中引入依赖</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><code class="hljs xml"><span class="hljs-comment">&lt;!-- spring-cloud-alibaba --&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">dependencyManagement</span>&gt;</span><br>   <span class="hljs-tag">&lt;<span class="hljs-name">dependencies</span>&gt;</span><br>      <span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span><br>         <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>com.alibaba.cloud<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span><br>         <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>spring-cloud-alibaba-dependencies<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span><br>         <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>2.2.6.RELEASE<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span><br>         <span class="hljs-tag">&lt;<span class="hljs-name">type</span>&gt;</span>pom<span class="hljs-tag">&lt;/<span class="hljs-name">type</span>&gt;</span><br>         <span class="hljs-tag">&lt;<span class="hljs-name">scope</span>&gt;</span>import<span class="hljs-tag">&lt;/<span class="hljs-name">scope</span>&gt;</span><br>      <span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span><br>   <span class="hljs-tag">&lt;/<span class="hljs-name">dependencies</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">dependencyManagement</span>&gt;</span><br></code></pre></td></tr></table></figure>

<p>之后有模块要使用 SpringCloud Alibaba 的组件的时候，直接添加依赖就行了，就不用指定版本了</p>
<h2 id="Nacos-注册中心"><a href="#Nacos-注册中心" class="headerlink" title="Nacos 注册中心"></a>Nacos 注册中心</h2><blockquote>
<p>Nacos 是阿里巴巴开源的一个更易于构建云原生应用的动态服务发现、配置管理和服务管理 平台</p>
</blockquote>
<p><a target="_blank" rel="noopener" href="https://nacos.io/zh-cn/docs/quick-start.html">Nacos快速开始文档</a></p>
<h3 id="下载配置-Nacos"><a href="#下载配置-Nacos" class="headerlink" title="下载配置 Nacos"></a>下载配置 Nacos</h3><p>下载地址：<a target="_blank" rel="noopener" href="https://github.com/alibaba/nacos/releases">https://github.com/alibaba/nacos/releases</a></p>
<p>下载后运行 bin/startup.cmd 文件就可以启动 nacos 服务</p>
<p>但是新版本运行会出现问题，因为 nacos 默认会以集群的方式运行，然后我们是单机运行，并没有配置 nacos 集群，所以出现问题，因此我们要修改 startup.cmd 文件，将运行方式改为单机模式</p>
<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/weixin_42982636/article/details/108221299">其他问题</a></p>
<p><img src="https://cdn.jsdelivr.net/gh/yechen-ops/image-hosting@master/20210925/image.26m9jz1o9nz4.png" srcset="/img/loading.gif" lazyload alt="默认的集群模式"></p>
<p><img src="https://cdn.jsdelivr.net/gh/yechen-ops/image-hosting@master/20210925/image.1ktzzi6qcpj4.png" srcset="/img/loading.gif" lazyload alt="修改后单机模式"></p>
<p>接下来就可以正常运行了</p>
<p>访问：<a target="_blank" rel="noopener" href="http://localhost:8848/nacos/index.html">http://localhost:8848/nacos/index.html</a> 登录，默认用户名和密码都是 nacos</p>
<p><img src="https://cdn.jsdelivr.net/gh/yechen-ops/image-hosting@master/20210925/image.2dhsxvlwtha8.png" srcset="/img/loading.gif" lazyload alt="nacos登录成功"></p>
<h3 id="在项目中使用-Nacos"><a href="#在项目中使用-Nacos" class="headerlink" title="在项目中使用 Nacos"></a>在项目中使用 Nacos</h3><p><a target="_blank" rel="noopener" href="https://github.com/alibaba/spring-cloud-alibaba/blob/master/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/readme-zh.md">官方教程</a></p>
<p><strong>首先</strong>，修改 pom.xml 文件，引入 Nacos Discovery Starter</p>
<p>由于我们所有的服务都需要使用 nacos 进行服务注册，因此将依赖加载 common 模块中，所有的服务都可以依赖引用</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs xml"><span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>com.alibaba.cloud<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>spring-cloud-starter-alibaba-nacos-discovery<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span><br></code></pre></td></tr></table></figure>

<p><strong>其次</strong>，在应用的 /src/main/resources/application.properties 配置文件中配置 Nacos Server 地址</p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><code class="hljs yaml"><span class="hljs-attr">spring:</span> <br>  <span class="hljs-attr">cloud:</span> <br>    <span class="hljs-attr">nacos:</span> <br>      <span class="hljs-attr">discovery:</span> <br>        <span class="hljs-comment"># 配置 Nacos Server 地址</span><br>        <span class="hljs-attr">server-addr:</span> <span class="hljs-number">127.0</span><span class="hljs-number">.0</span><span class="hljs-number">.1</span><span class="hljs-string">:8848</span><br>  <span class="hljs-attr">application:</span><br>    <span class="hljs-comment"># 配置服务名称</span><br>    <span class="hljs-attr">name:</span> <span class="hljs-string">gulimall-coupon</span><br></code></pre></td></tr></table></figure>

<p><strong>最后</strong>，在 SpringBoot 启动类上添加 <code>@EnableDiscoveryClinet</code> 注解，即可开启服务注册与发现功能，我们先将 coupon 与 member模块注册到 nscos 中</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@EnableDiscoveryClient</span><span class="hljs-comment">// 开启服务注册发现</span><br><span class="hljs-meta">@MapperScan(&quot;cn.yechen.gulimall.coupon.dao&quot;)</span><br><span class="hljs-meta">@SpringBootApplication</span><br><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">GulimallCouponApplication</span> </span>&#123;<br><br>   <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>&#123;<br>      SpringApplication.run(GulimallCouponApplication.class, args);<br>   &#125;<br><br>&#125;<br></code></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@EnableDiscoveryClient</span><span class="hljs-comment">// 开启服务注册发现</span><br><span class="hljs-meta">@MapperScan(&quot;cn.yechen.gulimall.member.dao&quot;)</span><br><span class="hljs-meta">@SpringBootApplication</span><br><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">GulimallMemberApplication</span> </span>&#123;<br><br>   <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>&#123;<br>      SpringApplication.run(GulimallMemberApplication.class, args);<br>   &#125;<br><br>&#125;<br></code></pre></td></tr></table></figure>

<p>此时，开启 nacos 并启动两个服务，就可以看到服务已经注册到 nacos 中了</p>
<p><img src="https://cdn.jsdelivr.net/gh/yechen-ops/image-hosting@master/20210925/image.2ulw5ksfpjs0.png" srcset="/img/loading.gif" lazyload alt="nacoc中的服务"></p>
<h2 id="Feign（远程调用）"><a href="#Feign（远程调用）" class="headerlink" title="Feign（远程调用）"></a>Feign（远程调用）</h2><p><strong>声明式远程调用</strong></p>
<p>feign 是一个声明式的 HTTP 客户端，他的目的就是让远程调用更加简单。给远程服务发的是HTTP请求。</p>
<p><a target="_blank" rel="noopener" href="https://spring.io/projects/spring-cloud#overview">boot 和 cloud 对应版本</a>：</p>
<table>
<thead>
<tr>
<th align="left">Release Train</th>
<th align="left">Boot Version</th>
</tr>
</thead>
<tbody><tr>
<td align="left"><a target="_blank" rel="noopener" href="https://github.com/spring-cloud/spring-cloud-release/wiki/Spring-Cloud-2020.0-Release-Notes">2020.0.x</a> aka Ilford</td>
<td align="left">2.4.x, 2.5.x (Starting with 2020.0.3)</td>
</tr>
<tr>
<td align="left"><a target="_blank" rel="noopener" href="https://github.com/spring-cloud/spring-cloud-release/wiki/Spring-Cloud-Hoxton-Release-Notes">Hoxton</a></td>
<td align="left">2.2.x, 2.3.x (Starting with SR5)</td>
</tr>
<tr>
<td align="left"><a target="_blank" rel="noopener" href="https://github.com/spring-projects/spring-cloud/wiki/Spring-Cloud-Greenwich-Release-Notes">Greenwich</a></td>
<td align="left">2.1.x</td>
</tr>
<tr>
<td align="left"><a target="_blank" rel="noopener" href="https://github.com/spring-projects/spring-cloud/wiki/Spring-Cloud-Finchley-Release-Notes">Finchley</a></td>
<td align="left">2.0.x</td>
</tr>
<tr>
<td align="left"><a target="_blank" rel="noopener" href="https://github.com/spring-projects/spring-cloud/wiki/Spring-Cloud-Edgware-Release-Notes">Edgware</a></td>
<td align="left">1.5.x</td>
</tr>
<tr>
<td align="left"><a target="_blank" rel="noopener" href="https://github.com/spring-projects/spring-cloud/wiki/Spring-Cloud-Dalston-Release-Notes">Dalston</a></td>
<td align="left">1.5.x</td>
</tr>
</tbody></table>
<p>我们在项目中使用 <code>SpringBoot 2.2.6 2.2.6.RELEASE</code> 的版本，因此引入 <code>SpringCloud Hoxton</code> 的版本</p>
<p>之前我们在创建项目时已经在每个模块中引入了 OpenFeign 依赖了，主要是</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><code class="hljs xml"><span class="hljs-tag">&lt;<span class="hljs-name">properties</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">spring-cloud.version</span>&gt;</span>Hoxton.SR9<span class="hljs-tag">&lt;/<span class="hljs-name">spring-cloud.version</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">properties</span>&gt;</span><br><br><span class="hljs-tag">&lt;<span class="hljs-name">dependencies</span>&gt;</span><br>    <br>    <span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.springframework.cloud<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>spring-cloud-starter-openfeign<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span><br>    <span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span><br><br><span class="hljs-tag">&lt;/<span class="hljs-name">dependencies</span>&gt;</span><br><br><span class="hljs-tag">&lt;<span class="hljs-name">dependencyManagement</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">dependencies</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.springframework.cloud<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>spring-cloud-dependencies<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>$&#123;spring-cloud.version&#125;<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">type</span>&gt;</span>pom<span class="hljs-tag">&lt;/<span class="hljs-name">type</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">scope</span>&gt;</span>import<span class="hljs-tag">&lt;/<span class="hljs-name">scope</span>&gt;</span><br>        <span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span><br>    <span class="hljs-tag">&lt;/<span class="hljs-name">dependencies</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">dependencyManagement</span>&gt;</span><br></code></pre></td></tr></table></figure>

<p>现在我们想在 member 模块中调用 coupon 模块中的一个接口，调用方法如下：</p>
<p><strong>一、在 coupon 中准备好一个被调用的接口</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@RestController</span><br><span class="hljs-meta">@RequestMapping(&quot;coupon/coupon&quot;)</span><br><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CouponController</span> </span>&#123;<br>    <br>    <span class="hljs-comment">// 会员的优惠券信息（测试远程调用）</span><br>    <span class="hljs-meta">@RequestMapping(&quot;/member/list&quot;)</span><br>    <span class="hljs-function"><span class="hljs-keyword">public</span> R <span class="hljs-title">memberCoupons</span><span class="hljs-params">()</span> </span>&#123;<br>        CouponEntity couponEntity = <span class="hljs-keyword">new</span> CouponEntity();<br>        couponEntity.setCouponName(<span class="hljs-string">&quot;满100减10&quot;</span>);<br>        <span class="hljs-keyword">return</span> R.ok().put(<span class="hljs-string">&quot;coupons&quot;</span>, Arrays.asList(couponEntity));<br>    &#125;<br>    <br>&#125;<br></code></pre></td></tr></table></figure>

<p><strong>二、在 member 中编写一个接口，接口告诉 springcloud 这个接口需要调用远程服务</strong></p>
<p>在 src/main/java/cn/yechen/gulimall/member/feign 包下创建这个接口</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@FeignClient(&quot;gulimall-coupon&quot;)</span><span class="hljs-comment">// 指定要调用的远程服务名称（在 nacos 中注册的服务名）</span><br><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">CouponFeignService</span> </span>&#123;<br><br>    <span class="hljs-comment">// 声明接口的每一个方法都是调用了远程调用服务的哪个请求</span><br>    <span class="hljs-meta">@RequestMapping(&quot;/coupon/coupon/member/list&quot;)</span><br>    <span class="hljs-function">R <span class="hljs-title">memberCoupons</span><span class="hljs-params">()</span></span>;<br><br>&#125;<br></code></pre></td></tr></table></figure>

<p><strong>三、在 member 中编写一个接口，调用 coupon 中的接口</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@RestController</span><br><span class="hljs-meta">@RequestMapping(&quot;member/member&quot;)</span><br><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MemberController</span> </span>&#123;<br>    <br>    <span class="hljs-meta">@RequestMapping(&quot;/coupons&quot;)</span><br>    <span class="hljs-function"><span class="hljs-keyword">public</span> R <span class="hljs-title">test</span><span class="hljs-params">()</span> </span>&#123;<br>        <span class="hljs-comment">// 本服务数据</span><br>        MemberEntity memberEntity = <span class="hljs-keyword">new</span> MemberEntity();<br>        memberEntity.setNickname(<span class="hljs-string">&quot;zhangsan&quot;</span>);<br><br>        <span class="hljs-comment">// 调用远程服务得到数据</span><br>        R r = couponFeignService.memberCoupons();<br>        Object coupons = r.get(<span class="hljs-string">&quot;coupons&quot;</span>);<br><br>        <span class="hljs-comment">// 返回数据</span><br>        <span class="hljs-keyword">return</span> R.ok().put(<span class="hljs-string">&quot;member&quot;</span>, memberEntity).put(<span class="hljs-string">&quot;coupons&quot;</span>, coupons);<br>    &#125;<br><br>&#125;<br></code></pre></td></tr></table></figure>

<p><strong>四、在 member 的启动类上添加 <code>@EnableFeignClients</code> 注解</strong>，这里要指定远程调用接口所在的包名</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@EnableFeignClients(basePackages = &quot;cn.yechen.gulimall.member.feign&quot;)</span><span class="hljs-comment">// 开启远程调用功能</span><br><span class="hljs-meta">@EnableDiscoveryClient</span><br><span class="hljs-meta">@MapperScan(&quot;cn.yechen.gulimall.member.dao&quot;)</span><br><span class="hljs-meta">@SpringBootApplication</span><br><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">GulimallMemberApplication</span> </span>&#123;<br><br>   <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>&#123;<br>      SpringApplication.run(GulimallMemberApplication.class, args);<br>   &#125;<br><br>&#125;<br></code></pre></td></tr></table></figure>

<p>启动服务，访问 <a target="_blank" rel="noopener" href="http://localhost:8000/member/member/coupons">http://localhost:8000/member/member/coupons</a></p>
<p><img src="https://cdn.jsdelivr.net/gh/yechen-ops/image-hosting@master/20210925/image.5qtyng3uqmo0.png" srcset="/img/loading.gif" lazyload alt="访问结果"></p>
<h2 id="nacos-配置中心"><a href="#nacos-配置中心" class="headerlink" title="nacos 配置中心"></a>nacos 配置中心</h2><p>我们还可以用 nacos 作为配置中心。</p>
<p>配置中心的意思是不在 application.properties 等文件中配置了，而是放到 nacos 配置中心公用，这样在修改配置文件的时候无需每台机器都改。</p>
<p><a target="_blank" rel="noopener" href="https://github.com/alibaba/spring-cloud-alibaba/blob/master/spring-cloud-alibaba-examples/nacos-example/nacos-config-example/readme-zh.md">官方教程</a></p>
<p><strong>首先</strong>，修改 pom.xml 文件，引入 Nacos Config Starter，我们还是在 common 模块中引入</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs xml"><span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>com.alibaba.cloud<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>spring-cloud-starter-alibaba-nacos-config<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span><br></code></pre></td></tr></table></figure>

<p><strong>其次</strong>，在应用的 /src/main/resources/<strong>bootstrap.properties</strong> 配置文件中配置 Nacos Config 元数据，我们在 coupon 模块下创建了 bootstrap.properties 文件，写入配置</p>
<figure class="highlight properties"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs properties"><span class="hljs-meta">spring.application.name</span>=<span class="hljs-string">gulimall-coupon</span><br><span class="hljs-meta">spring.cloud.nacos.config.server-addr</span>=<span class="hljs-string">127.0.0.1:8848</span><br></code></pre></td></tr></table></figure>

<p><strong>完成上述两步后</strong>，应用会从 Nacos Config 中获取相应的配置，并添加在 Spring Environment 的 PropertySources 中，我们可以使用 <code>@Value(&quot;$&#123;key&#125;&quot;)</code> 注解从配置文件将数据注入到变量中，使用 <code>@RefreshScope</code> 注解开启动态刷新功能</p>
<blockquote>
<p><strong>注：</strong>使用 nacos 配置中心 后，配置的数据会优先从 nacos 配置中心中获取，因此就算在本地的 application.properties 文件中有配置数据，也不会引用。</p>
</blockquote>
<p>在 coupon 模块中的一个 controller 中添加测试接口</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@RefreshScope</span><span class="hljs-comment">// 开启动态刷新功能</span><br><span class="hljs-meta">@RestController</span><br><span class="hljs-meta">@RequestMapping(&quot;coupon/coupon&quot;)</span><br><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CouponController</span> </span>&#123;<br><br>    <span class="hljs-comment">// 从配置中心注入数据</span><br>    <span class="hljs-meta">@Value(&quot;$&#123;my.name&#125;&quot;)</span><br>    <span class="hljs-keyword">private</span> String name;<br>    <span class="hljs-meta">@Value(&quot;$&#123;my.age&#125;&quot;)</span><br>    <span class="hljs-keyword">private</span> String age;<br><br>    <span class="hljs-comment">// 测试配置中心</span><br>    <span class="hljs-meta">@RequestMapping(&quot;/test&quot;)</span><br>    <span class="hljs-function"><span class="hljs-keyword">public</span> R <span class="hljs-title">testNacosConfig</span><span class="hljs-params">()</span> </span>&#123;<br>        <br>        <span class="hljs-keyword">return</span> R.ok().put(<span class="hljs-string">&quot;name&quot;</span>, name).put(<span class="hljs-string">&quot;age&quot;</span>, age);<br>        <br>    &#125;<br><br>&#125;<br></code></pre></td></tr></table></figure>

<p>接下来我们就要在 nacos 中添加配置文件了</p>
<p><img src="https://cdn.jsdelivr.net/gh/yechen-ops/image-hosting@master/20210925/image.7ed885n6dfs0.png" srcset="/img/loading.gif" lazyload alt="添加配置"></p>
<p><img src="https://cdn.jsdelivr.net/gh/yechen-ops/image-hosting@master/20210925/image.3cmknyz9qvc0.png" srcset="/img/loading.gif" lazyload alt="配置文件编写"></p>
<p>启动服务，访问接口：<a target="_blank" rel="noopener" href="http://localhost:7000/coupon/coupon/test">http://localhost:7000/coupon/coupon/test</a></p>
<p><img src="https://cdn.jsdelivr.net/gh/yechen-ops/image-hosting@master/20210925/image.2d6rxmpo3nwg.png" srcset="/img/loading.gif" lazyload alt="测试结果"></p>
<p>之后要是在 nacos 中修改配置文件，改配置可以马上生效，不用再重启服务了</p>
<h2 id="配置中心进阶"><a href="#配置中心进阶" class="headerlink" title="配置中心进阶"></a>配置中心进阶</h2><p>在 nacos 中还可以配置：</p>
<ul>
<li><strong>命名空间</strong>：主要用作配置隔离，可以是<strong>开发环境之间</strong>的隔离，也可以是每个<strong>服务之间</strong>进行隔离，默认的命名空间是 <code>public</code></li>
<li><strong>配置集</strong>：一组相关或不相关配置项的集合，就是一个概念</li>
<li><strong>配置集 ID</strong>：类似于配置文件名，即在 nacos 中添加配置文件时的 Data ID</li>
<li><strong>配置分组</strong>：默认所有的配置集都属于<code>DEFAULT_GROUP</code></li>
</ul>
<p><strong>一般的配置方案</strong>：每个微服务创建自己的命名空间，然后使用配置分组区分环境（dev/test/prod）</p>
<p>如我们可以将 coupon 服务和 mamber 服务都隔离为不同的命名空间，在使用不同的配置分组区分环境</p>
<p><img src="https://cdn.jsdelivr.net/gh/yechen-ops/image-hosting@master/20210925/image.64vyvw6zpg80.png" srcset="/img/loading.gif" lazyload alt="新建两个命名空间"></p>
<p><img src="https://cdn.jsdelivr.net/gh/yechen-ops/image-hosting@master/20210925/image.618bm6ziy9k0.png" srcset="/img/loading.gif" lazyload alt="dev分组下的配置"></p>
<p><img src="https://cdn.jsdelivr.net/gh/yechen-ops/image-hosting@master/20210925/image.7hmzoxsnfds0.png" srcset="/img/loading.gif" lazyload alt="prod分组下的配置"></p>
<p>此时我们可以看到在 coupon 命名空间下有两个不同的分组配置</p>
<p><img src="https://cdn.jsdelivr.net/gh/yechen-ops/image-hosting@master/20210925/image.3iswlvs2i1q0.png" srcset="/img/loading.gif" lazyload alt="分组配置"></p>
<p>我们之后就可以在 bootstrap.properties 文件中指定配置的命名空间和配置分组</p>
<figure class="highlight properties"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><code class="hljs properties"><span class="hljs-meta">spring.application.name</span>=<span class="hljs-string">gulimall-coupon</span><br><span class="hljs-meta">spring.cloud.nacos.config.server-addr</span>=<span class="hljs-string">127.0.0.1:8848</span><br><span class="hljs-comment"># 设置命名空间（注意值是命名空间的 ID）</span><br><span class="hljs-meta">spring.cloud.nacos.config.namespace</span>=<span class="hljs-string">04fd74be-2360-40c4-a757-a17d882cef5e</span><br><span class="hljs-comment"># 设置配置分组</span><br><span class="hljs-meta">spring.cloud.nacos.config.group</span>=<span class="hljs-string">dev</span><br></code></pre></td></tr></table></figure>

<p>这个时候运行服务，获取到的配置就是指定的配置了</p>
<p><img src="https://cdn.jsdelivr.net/gh/yechen-ops/image-hosting@master/20210925/image.5t6cgnrbr740.png" srcset="/img/loading.gif" lazyload alt="测试结果"></p>
<p><strong>加载多个配置到一个服务中</strong></p>
<p>例如我将 coupon 服务中的核心配置文件 application.yml 文件中的配置都写在 nacos 中，并且按照其左右分类配置</p>
<p><img src="https://cdn.jsdelivr.net/gh/yechen-ops/image-hosting@master/20210925/image.2hxwmohp7cy0.png" srcset="/img/loading.gif" lazyload alt="多个配置文件"></p>
<p>如果要使用这些配置到一个服务中，就要在 bootstrap.properties文件中指定</p>
<figure class="highlight properties"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><code class="hljs properties"><span class="hljs-meta">spring.application.name</span>=<span class="hljs-string">gulimall-coupon</span><br><span class="hljs-meta">spring.cloud.nacos.config.server-addr</span>=<span class="hljs-string">127.0.0.1:8848</span><br><span class="hljs-comment"># 设置命名空间（注意值是命名空间的 ID）</span><br><span class="hljs-meta">spring.cloud.nacos.config.namespace</span>=<span class="hljs-string">04fd74be-2360-40c4-a757-a17d882cef5e</span><br><span class="hljs-comment"># 设置配置分组</span><br><span class="hljs-meta">spring.cloud.nacos.config.group</span>=<span class="hljs-string">dev</span><br><span class="hljs-comment"></span><br><span class="hljs-comment"># 数组形式指定 DataID</span><br><span class="hljs-meta">spring.cloud.nacos.config.extension-configs[0].data-id</span>=<span class="hljs-string">datasource.yml</span><br><span class="hljs-comment"># 指定 配置分组</span><br><span class="hljs-meta">spring.cloud.nacos.config.extension-configs[0].group</span>=<span class="hljs-string">dev</span><br><span class="hljs-comment"># 指定当配置更新的时候是否刷新配置</span><br><span class="hljs-meta">spring.cloud.nacos.config.extension-configs[0].refresh</span>=<span class="hljs-string">true</span><br><br><span class="hljs-meta">spring.cloud.nacos.config.extension-configs[1].data-id</span>=<span class="hljs-string">mybatis.yml</span><br><span class="hljs-meta">spring.cloud.nacos.config.extension-configs[1].group</span>=<span class="hljs-string">dev</span><br><span class="hljs-meta">spring.cloud.nacos.config.extension-configs[1].refresh</span>=<span class="hljs-string">true</span><br><br><span class="hljs-meta">spring.cloud.nacos.config.extension-configs[2].data-id</span>=<span class="hljs-string">server.yml</span><br><span class="hljs-meta">spring.cloud.nacos.config.extension-configs[2].group</span>=<span class="hljs-string">dev</span><br><span class="hljs-meta">spring.cloud.nacos.config.extension-configs[2].refresh</span>=<span class="hljs-string">true</span><br></code></pre></td></tr></table></figure>

<p>此时启动服务，我们在控制台中可以看到引用了那些配置文件，其中一条日志</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs txt">2021-09-25 21:48:25.064  INFO 27476 --- [           main] b.c.PropertySourceBootstrapConfiguration : <br>Located property source: [<br>BootstrapPropertySource &#123;name=&#x27;bootstrapProperties-gulimall-coupon.properties,dev&#x27;&#125;, <br>BootstrapPropertySource &#123;name=&#x27;bootstrapProperties-gulimall-coupon,dev&#x27;&#125;, <br>BootstrapPropertySource &#123;name=&#x27;bootstrapProperties-server.yml,dev&#x27;&#125;, <br>BootstrapPropertySource &#123;name=&#x27;bootstrapProperties-mybatis.yml,dev&#x27;&#125;, <br>BootstrapPropertySource &#123;name=&#x27;bootstrapProperties-datasource.yml,dev&#x27;&#125;]<br></code></pre></td></tr></table></figure>

<p>可以看到配置文件都被引入了</p>
<h2 id="API-网关-Gateway"><a href="#API-网关-Gateway" class="headerlink" title="API 网关 Gateway"></a>API 网关 Gateway</h2><blockquote>
<p>SpringCloud Gateway 是 Spring Cloud 的一个全新项目，该项目是基于 Spring 5.0，Spring Boot 2.0 和 Project Reactor 等技术开发的网关，它旨在为微服务架构提供一种简单有效的统一的 API 路由管理方式。</p>
<p>SpringCloud Gateway 作为 Spring Cloud 生态系统中的网关，目标是替代 Zuul，在 Spring Cloud 2.0 以上版本中，没有对新版本的 Zuul 2.0 以上最新高性能版本进行集成，仍然还是使用的 Zuul 2.0 之前的非 Reactor 模式的老版本。而为了提升网关的性能，SpringCloud Gateway 是基于 WebFlux 框架实现的，而 WebFlux 框架底层则使用了高性能的 Reactor 模式通信框架 Netty。</p>
<p>Spring Cloud Gateway 的目标，不仅提供统一的路由方式，并且基于 Filter 链的方式提供了网关基本的功能，例如：安全，监控/指标，和限流。</p>
<p>提前声明：<strong>Spring Cloud Gateway 底层使用了高性能的通信框架Netty</strong>。</p>
</blockquote>
<p><strong>三大核心概念：</strong></p>
<p>（1）<strong>Filter（过滤器）：</strong></p>
<p>可以使用它拦截和修改请求，并且对上游的响应，进行二次处理。<a target="_blank" rel="noopener" href="https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#gatewayfilter-factories">官网</a></p>
<p>（2）<strong>Route（路由）：</strong></p>
<p>网关配置的基本组成模块。一个 <strong>Route 模块</strong>由一个 ID，一个目标 URI，一组断言和一组过滤器定义。如果断言为真，则路由匹配，目标 URI 会被访问。<a target="_blank" rel="noopener" href="https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#gateway-request-predicates-factories">官网</a></p>
<p>（3）<strong>Predicate（断言）：</strong></p>
<p>这是一个 Java 8 的 Predicate，可以使用它来匹配来自 HTTP 请求的任何内容，例如 headers 或参数。<strong>断言的</strong>输入类型是一个 ServerWebExchange。</p>
<p><strong>Spring Cloud Gateway 的处理流程</strong></p>
<p>客户端向 Spring Cloud Gateway 发出请求。然后在 Gateway Handler Mapping 中找到与请求相匹配的路由，将其发送到 Gateway Web Handler。Handler 再通过指定的过滤器链来将请求发送到我们实际的服务执行业务逻辑，然后返回。过滤器之间用虚线分开是因为过滤器可能会在发送代理请求之前（“pre”）或之后（“post”）执行业务逻辑。</p>
<p><img src="https://cdn.jsdelivr.net/gh/yechen-ops/image-hosting@master/20210925/image.ydt1yqr1ws0.png" srcset="/img/loading.gif" lazyload alt="Spring Cloud Gateway 的处理流程"></p>
<p><strong>简单使用一下</strong></p>
<p>先创建一个 springboot 工程，加入到 gulimall 父工程中，在这个工程中依赖 SpringCloud Gateway </p>
<p>在 applicaiton.yml 中配置简单的路由规则，进行网页转发</p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><code class="hljs yaml"><span class="hljs-attr">spring:</span><br>  <span class="hljs-attr">cloud:</span><br>    <span class="hljs-attr">gateway:</span><br>      <span class="hljs-attr">routes:</span><br>      <span class="hljs-bullet">-</span> <span class="hljs-attr">id:</span> <span class="hljs-string">test_route</span><br>        <span class="hljs-attr">uri:</span> <span class="hljs-string">https://www.baidu.com</span><br>        <span class="hljs-attr">predicates:</span><br>        <span class="hljs-bullet">-</span> <span class="hljs-string">Query=url,baidu</span><br><br>      <span class="hljs-bullet">-</span> <span class="hljs-attr">id:</span> <span class="hljs-string">qq_route</span><br>        <span class="hljs-attr">uri:</span> <span class="hljs-string">https://www.qq.com</span><br>        <span class="hljs-attr">predicates:</span><br>        <span class="hljs-bullet">-</span> <span class="hljs-string">Query=url,qq</span><br>  <span class="hljs-attr">application:</span><br>    <span class="hljs-attr">name:</span> <span class="hljs-string">gulimall-gatewall</span><br><span class="hljs-attr">server:</span><br>  <span class="hljs-attr">port:</span> <span class="hljs-number">88</span><br></code></pre></td></tr></table></figure>

<p>配置启动类：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@EnableDiscoveryClient</span><span class="hljs-comment">// 服务注册</span><br><span class="hljs-meta">@SpringBootApplication(exclude = &#123;DataSourceAutoConfiguration.class, IdentifierGeneratorAutoConfiguration.class&#125;)</span><span class="hljs-comment">// 排除数据库相关的自动配置</span><br><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">GulimallGatewallApplication</span> </span>&#123;<br><br>   <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>&#123;<br>      SpringApplication.run(GulimallGatewallApplication.class, args);<br>   &#125;<br><br>&#125;<br></code></pre></td></tr></table></figure>

<p><img src="https://cdn.jsdelivr.net/gh/yechen-ops/image-hosting@master/20210925/image.1zcn9xk3sls0.png" srcset="/img/loading.gif" lazyload alt="网页转发"></p>

            </div>
            <hr>
            <div>
              <div class="post-metas mb-3">
                
                  <div class="post-meta mr-3">
                    <i class="iconfont icon-category"></i>
                    
                      <a class="hover-with-bg" href="/categories/Java-%E9%A1%B9%E7%9B%AE/">Java 项目</a>
                    
                      <a class="hover-with-bg" href="/categories/Java-%E9%A1%B9%E7%9B%AE/%E8%B0%B7%E7%B2%92%E5%95%86%E5%9F%8E/">谷粒商城</a>
                    
                  </div>
                
                
                  <div class="post-meta">
                    <i class="iconfont icon-tags"></i>
                    
                      <a class="hover-with-bg" href="/tags/Java-%E9%A1%B9%E7%9B%AE/">Java 项目</a>
                    
                      <a class="hover-with-bg" href="/tags/%E8%B0%B7%E7%B2%92%E5%95%86%E5%9F%8E/">谷粒商城</a>
                    
                  </div>
                
              </div>
              
                <p class="note note-warning">
                  
                    本博客所有文章除特别声明外，均采用 <a target="_blank" href="https://creativecommons.org/licenses/by-sa/4.0/deed.zh" rel="nofollow noopener noopener">CC BY-SA 4.0 协议</a> ，转载请注明出处！
                  
                </p>
              
              
                <div class="post-prevnext">
                  <article class="post-prev col-6">
                    
                    
                      <a href="/2021/10/02/SpringBoot-SpringBoot%E7%AE%80%E5%8D%95%E4%BD%BF%E7%94%A8-2021-10-02-SpringBoot%E6%9B%B4%E6%8D%A2%E5%90%AF%E5%8A%A8logo/">
                        <i class="iconfont icon-arrowleft"></i>
                        <span class="hidden-mobile">SpringBoot更换启动logo</span>
                        <span class="visible-mobile">上一篇</span>
                      </a>
                    
                  </article>
                  <article class="post-next col-6">
                    
                    
                      <a href="/2021/09/25/%E8%B0%B7%E7%B2%92%E5%95%86%E5%9F%8E%E9%A1%B9%E7%9B%AE-2021-09-25-1-%E9%A1%B9%E7%9B%AE%E4%BB%8B%E7%BB%8D%E5%8F%8A%E5%9F%BA%E7%A1%80%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA/">
                        <span class="hidden-mobile">1.项目介绍及基础环境搭建</span>
                        <span class="visible-mobile">下一篇</span>
                        <i class="iconfont icon-arrowright"></i>
                      </a>
                    
                  </article>
                </div>
              
            </div>

            
          </article>
        </div>
      </div>
    </div>
    
      <div class="d-none d-lg-block col-lg-2 toc-container" id="toc-ctn">
        <div id="toc">
  <p class="toc-header"><i class="iconfont icon-list"></i>&nbsp;目录</p>
  <div class="toc-body" id="toc-body"></div>
</div>

      </div>
    
  </div>
</div>

<!-- Custom -->


    

    
      <a id="scroll-top-button" href="#" role="button">
        <i class="iconfont icon-arrowup" aria-hidden="true"></i>
      </a>
    

    
      <div class="modal fade" id="modalSearch" tabindex="-1" role="dialog" aria-labelledby="ModalLabel"
     aria-hidden="true">
  <div class="modal-dialog modal-dialog-scrollable modal-lg" role="document">
    <div class="modal-content">
      <div class="modal-header text-center">
        <h4 class="modal-title w-100 font-weight-bold">搜索</h4>
        <button type="button" id="local-search-close" class="close" data-dismiss="modal" aria-label="Close">
          <span aria-hidden="true">&times;</span>
        </button>
      </div>
      <div class="modal-body mx-3">
        <div class="md-form mb-5">
          <input type="text" id="local-search-input" class="form-control validate">
          <label data-error="x" data-success="v"
                 for="local-search-input">关键词</label>
        </div>
        <div class="list-group" id="local-search-result"></div>
      </div>
    </div>
  </div>
</div>
    

    
  </main>

  <footer class="text-center mt-5 py-3">
  <div class="footer-content">
     <a href="https://hexo.io" target="_blank" rel="nofollow noopener"><span>Hexo</span></a> <i class="iconfont icon-love"></i> <a href="https://github.com/fluid-dev/hexo-theme-fluid" target="_blank" rel="nofollow noopener"><span>Fluid</span></a> 
  </div>
  

  

  
</footer>


  <!-- SCRIPTS -->
  
  <script  src="https://cdn.jsdelivr.net/npm/nprogress@0.2.0/nprogress.min.js" ></script>
  <link  rel="stylesheet" href="https://cdn.jsdelivr.net/npm/nprogress@0.2.0/nprogress.min.css" />

  <script>
    NProgress.configure({"showSpinner":false,"trickleSpeed":100})
    NProgress.start()
    window.addEventListener('load', function() {
      NProgress.done();
    })
  </script>


<script  src="https://cdn.jsdelivr.net/npm/jquery@3.6.0/dist/jquery.min.js" ></script>
<script  src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.0/dist/js/bootstrap.min.js" ></script>
<script  src="/js/events.js" ></script>
<script  src="/js/plugins.js" ></script>

<!-- Plugins -->


  
    <script  src="/js/img-lazyload.js" ></script>
  



  



  <script  src="https://cdn.jsdelivr.net/npm/tocbot@4.12.3/dist/tocbot.min.js" ></script>



  <script  src="https://cdn.jsdelivr.net/npm/@fancyapps/fancybox@3.5.7/dist/jquery.fancybox.min.js" ></script>



  <script  src="https://cdn.jsdelivr.net/npm/anchor-js@4.3.1/anchor.min.js" ></script>



  <script defer src="https://cdn.jsdelivr.net/npm/clipboard@2.0.8/dist/clipboard.min.js" ></script>



  <script  src="/js/local-search.js" ></script>






  <script  src="https://cdn.jsdelivr.net/npm/typed.js@2.0.12/lib/typed.min.js" ></script>
  <script>
    (function (window, document) {
      var typing = Fluid.plugins.typing;
      var title = document.getElementById('subtitle').title;
      
      typing(title)
      
    })(window, document);
  </script>














  
<script src="//cdn.jsdelivr.net/gh/bynotes/texiao/source/js/xiaoxuehua.js"></script>
<script src="//cdn.jsdelivr.net/gh/bynotes/texiao/source/js/caidai.js"></script>
<script src="//cdn.jsdelivr.net/gh/bynotes/texiao/source/js/love.js"></script>
<script src="//cdn.jsdelivr.net/npm/aplayer/dist/APlayer.min.js"></script>
<script src="//cdn.jsdelivr.net/gh/metowolf/MetingJS@1.2/dist/Meting.min.js"></script>



<!-- 主题的启动项 保持在最底部 -->
<script  src="/js/boot.js" ></script>

  <!--动态线条背景-->
  <script type="text/javascript" color="70,119,184" opacity='1' zIndex="-2" count="200" src="//cdn.bootcss.com/canvas-nest.js/1.0.0/canvas-nest.min.js"></script>

<script src="/live2dw/lib/L2Dwidget.min.js?094cbace49a39548bed64abff5988b05"></script><script>L2Dwidget.init({"model":{"jsonPath":"/live2dw/assets/koharu.model.json"},"display":{"position":"left","width":200,"height":400},"mobile":{"show":false},"log":false,"pluginJsPath":"lib/","pluginModelPath":"assets/","pluginRootPath":"live2dw/","tagMode":false});</script></body>
</html>
